package com.katze.common.ws.core;

import com.katze.common.ws.config.WebSocketProperties;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.ServerChannel;
import io.netty.channel.epoll.Epoll;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class NettyWebSocketServer {

    private static final Logger log = LoggerFactory.getLogger(NettyWebSocketServer.class);

    // 消息调度
    private final MessageDispatcher dispatcher;
    // 配置参数
    private final WebSocketProperties properties;

    // Netty 组件
    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;
    private ChannelFuture serverChannelFuture;

    public NettyWebSocketServer( WebSocketProperties properties, MessageDispatcher dispatcher) {
        this.properties = properties;
        this.dispatcher = dispatcher;
    }

    /**
     * 启动 WebSocket 服务
     */
    public void start() throws InterruptedException {
        Class<? extends ServerChannel> channelClass;
        // 根据操作系统选择最佳IO模型
        if (Epoll.isAvailable()) {
            channelClass = EpollServerSocketChannel.class;
            this.bossGroup = new EpollEventLoopGroup(1, new DefaultThreadFactory("ws-boss"));
            this.workerGroup = new EpollEventLoopGroup(new DefaultThreadFactory("ws-worker"));
        } else {
            channelClass = NioServerSocketChannel.class;
            this.bossGroup = new NioEventLoopGroup(1, new DefaultThreadFactory("ws-boss"));
            this.workerGroup = new NioEventLoopGroup(new DefaultThreadFactory("ws-worker"));
        }

        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap
                .group(bossGroup, workerGroup)
                .channel(channelClass)
                .handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new DefaultChannelInitializer(dispatcher, properties));

        // TCP 参数调优
        bootstrap.option(ChannelOption.SO_REUSEADDR, true)
                .option(ChannelOption.SO_BACKLOG, 1024)
                .childOption(ChannelOption.TCP_NODELAY, true)
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);

        this.serverChannelFuture = bootstrap.bind(properties.getPort()).sync();
        log.info("WebSocket服务已启动，端口: " + properties.getPort());
    }

    /**
     * 停止 WebSocket 服务
     */
    public void stop() {
        if (serverChannelFuture != null) {
            serverChannelFuture.channel().close();
        }
        workerGroup.shutdownGracefully();
        bossGroup.shutdownGracefully();
        log.info("WebSocket服务已停止");
    }
}
